/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package databook.util;

import databook.util.CSVReader;

import databook.controller.Props;

import java.io.*;
import java.util.*;

/**
 *
 * @author zach
 */
public class CSVConvert {

    /*
    private static String[] wantedHeaders = {"COHORT_TERM","LSA_GENDER_LD","LSA_RACE_LD","LSA_NEW_CONT_STATUS","major_1","MAJOR_2","MAJOR_3","MAJOR_4","MAJOR_5","MAJOR_6","MAJOR_7","MAJOR_8","MAJOR_9","MAJOR_10","MAJOR_11","MAJOR_12","MAJOR_13","DEG_SEM","DEG_1","DEG_2","DEG_3","DEG_4","DEG_5","DEG_6","DEG_7","DEG_8","DEG_9","DEG_10","DEG_11","DEG_12","DEG_13"};
    
    private static String[] tables = {"student","major","department","hasMajor"};
    private static String[][] tableHeaders = {  {"Student_ID","Gender","Ethnicity","Graduated","Transfered"},
                                                {"Major_ID","Dept_ID","Designator","Full_Name"},
                                                {"Department_ID","Name"},
                                                {"Student_ID","Major_ID","Year","Semester"}};
                                            
    private static PrintWriter[] handles = new PrintWriter[tables.length];
    private static PrintWriter[] stats = new PrintWriter[tables.length];
    
    private static int studentId = 0;
    private static int majorId = 0;
    private static int deptId = 0;
    private static int hasMajorId = 0;
    
    private static HashMap<String,Integer> majorMap = new HashMap<String,Integer>();
    private static HashMap<String,Integer> deptMap = new HashMap<String,Integer>();
    private static Vector<String[]> majorChangeQ = new Vector<String[]>();
    /**/
    
    public static void convert2CSV(String src, String edgePrefix, String nodePrefix, String treeSuffix, boolean overwrite) throws FileNotFoundException, IOException {
        if (edgePrefix == null) {
            edgePrefix = "edge";
        }
        if (nodePrefix == null) {
            nodePrefix = "node";
        }
        if (treeSuffix == null) {
            treeSuffix = "_tree.csv";
        }
        
        String currTerm = Props.getString(Props.CURRENT_TERM);
        
        File src_file = new File(src);
        //File e_file = new File(edgePrefix + ".csv");
        File et_file = new File(edgePrefix + treeSuffix);
        //File n_file = new File(nodePrefix + ".csv");
        File nt_file = new File(nodePrefix + treeSuffix);

        //if (!src_file.exists() || (!overwrite && e_file.exists() && n_file.exists() && et_file.exists() && nt_file.exists())) 
        if (!src_file.exists() || (!overwrite && et_file.exists() && nt_file.exists())) 
            return;
       
        BufferedReader reader = new BufferedReader(new FileReader(src_file));
        String[] headers = reader.readLine().split(",");
        //int[] colNums = getHeaderColumns(headers,wantedHeaders);
        int[] colNums = new int[headers.length];
        for (int i = 0; i < colNums.length; i++) {
            colNums[i] = i;
        }
        
        String input = "";
        String[] edgeHeaders = {"COLLEGE_FROM","COLLEGE_TO","DEPT_FROM","DEPT_TO","MAJOR_FROM","MAJOR_TO","TERM_FROM","TERM_TO","GRADUATED","GENDER","RACE","WEIGHT"};
        //String[] edgeHeaders = {"COLLEGE_FROM","COLLEGE_TO","DEPT_FROM","DEPT_TO","MAJOR_FROM","MAJOR_TO","TERM_FROM","TERM_TO","GRADUATED","GENDER","RACE","STU_LEVEL","WEIGHT"};
        String[] nodeHeaders = {"COLLEGE","DEPT","MAJOR","TERM","GRADUATED","GENDER","RACE","WEIGHT"};
        //String[] nodeHeaders = {"COLLEGE","DEPT","MAJOR","TERM","GRADUATED","GENDER","RACE","STU_LEVEL","WEIGHT"};

        HashMap<String,Integer> edgeMap = new HashMap();
        HashMap<String,Integer> nodeMap = new HashMap();
        Vector<String> nodeIndex = new Vector();
        Vector<String> edgeIndex = new Vector();
        int numSem = 13;
        while ((input = reader.readLine()) != null) {
            String[] cols = CSVReader.readLine(input,colNums);
            HashMap<String,String> row = createHash(headers,cols);
            String gender = row.get("LSA_GENDER_LD").equals("Female") ? "F" : "M";
            String race = row.get("LSA_RACE_LD");
            
            String major = row.get("major_1");
            String studentLevel = row.get("stu_level_1");
            int year = Integer.parseInt(row.get("COHORT_TERM").substring(0,4));
            int sem = Integer.parseInt(row.get("COHORT_TERM").substring(4,6));
            if (sem < 7) sem = 1;
            else sem = 2;
            String graduated = row.get("DEG_SEM").equals("") ? new String(year+"-"+sem).compareTo(currTerm) < 0 ? "N" : "Not Yet" : "Y";
            if (graduated.equals("N")) {
                for (int i = ((sem+1)%2)+1,j=2; i < (numSem + ((sem+1)%2)); i++,j++) {
                    String tyear = (year + (int)(i/2) + "-" +((i%2)+1));
                    if (tyear.compareTo(currTerm) > 0) i = numSem+1;
                    if (tyear.equals(currTerm) && !row.get("MAJOR_" + j).equals("")) {
                        graduated = "Not Yet";
                        i = numSem+1;
                    }
                }
            }
            checkAdd(nodeMap,new String[] { MajorMap.getCollege(major),
                                            MajorMap.getDepartment(major),
                                            major,
                                            year + "-" + sem,
                                            graduated,
                                            gender,
                                            race,
                                            //,studentLevel
                                            });
            if (!nodeIndex.contains(major))
                nodeIndex.add(major);
            for (int i = 2; i <= numSem; i++) {
                int n_year = year;
                int n_sem = sem;
                if ((n_sem % 2) == 0) {
                    n_year++;
                    n_sem = 1;
                } else {
                    n_sem = 2;
                }
                String newMajor = row.get("MAJOR_" + i);
                studentLevel = row.get("STU_LEVEL_" + i);
                if (!newMajor.equals("")) {
                    checkAdd(nodeMap,new String[] { MajorMap.getCollege(newMajor),
                                                    MajorMap.getDepartment(newMajor),
                                                    newMajor,
                                                    n_year + "-" + n_sem,
                                                    graduated,
                                                    gender,
                                                    race
                                                    //,studentLevel
                                                    });
                    if (!newMajor.equals(major)) {
                        if (!nodeIndex.contains(newMajor))
                            nodeIndex.add(newMajor);
                        if (!edgeIndex.contains(nodeIndex.indexOf(major) + "," + nodeIndex.indexOf(newMajor))) 
                            edgeIndex.add(nodeIndex.indexOf(major) + "," + nodeIndex.indexOf(newMajor));
                        checkAdd(edgeMap,new String[] { MajorMap.getCollege(major),
                                                        MajorMap.getCollege(newMajor),
                                                        MajorMap.getDepartment(major),
                                                        MajorMap.getDepartment(newMajor),
                                                        major,
                                                        newMajor,
                                                        year + "-" + sem,
                                                        n_year + "-" + n_sem,
                                                        graduated,
                                                        gender,
                                                        race
                                                        //,studentLevel
                                                        });
                        major = newMajor;
                        
                    }
                }
                year = n_year;
                sem = n_sem;
            }
        }
        if (overwrite || !et_file.exists()) 
            writeToFile(edgeHeaders,edgeMap,et_file);
        if (overwrite || !nt_file.exists()) 
            writeToFile(nodeHeaders,nodeMap,nt_file);
    }
    
    
    public static void writeToFile(String[] headers,HashMap<String,Integer> map,File file) throws FileNotFoundException {
        PrintWriter pw = new PrintWriter(file);
        pw.println(DatabookLib.arrayJoin(headers, ","));
        Iterator keys = map.keySet().iterator();
        int i = 0;
        while (keys.hasNext()) {
            String key = (String)keys.next();
            int weight = map.get(key).intValue();
            pw.println(key + "," + weight);
            i++;
        }
        pw.close();
    }
    
    public static void checkAdd(HashMap<String,Integer> map, String[] keys) {
        for (int i = 0; i < keys.length; i++) {
            if (keys[i].indexOf(',') > -1)
                keys[i] = "\"" + keys[i] + "\"";
        }
        String key = DatabookLib.arrayJoin(keys,",");
        if (map.containsKey(key)) {
            map.put(key,new Integer(map.get(key).intValue()+1));
        } else {
            map.put(key,new Integer(1));
        }
    }
    
    
    public static HashMap createHash(String[] keys, String[] values) {
        HashMap<String,String> map = new HashMap(keys.length);
        for (int i = 0; i < keys.length; i++) {
            try {
                map.put(keys[i],values[i]);
            } catch (ArrayIndexOutOfBoundsException aioob) {
                System.err.println("values must have the same length as keys: " + keys.length + " " + values.length);
            }
        }
        return map;
    }
    
    /*
    public static void convert2DB(String src, String dest) throws FileNotFoundException, IOException {
        File source = new File(src);
           
        if (source.exists()) {
            File destDir = new File(dest);
            if (!source.exists()) {
                throw new FileNotFoundException("Source File was not found: " + src);
            }
            if (destDir.exists() && !destDir.isDirectory()) {
                throw new IOException(dest + " is not a directory and already exists");
            }
            if (!destDir.exists() && !destDir.mkdir()) {
                throw new IOException("Could not create directory " + dest);
            }

            for (int i = 0; i < tables.length; i++) {
                File table = new File(destDir.getAbsolutePath() + File.separator + tables[i]);
                File metaTable = new File(destDir.getAbsolutePath() + File.separator + "." + tables[i]);
                table.delete();
                table.createNewFile();
                metaTable.delete();
                metaTable.createNewFile();
                handles[i] = new PrintWriter(table);
                handles[i].println(DatabookLib.arrayJoin(tableHeaders[i], ","));
                
                stats[i] = new PrintWriter(metaTable);
            }
            BufferedReader reader = new BufferedReader(new FileReader(source));
            String[] headers = reader.readLine().split(",");
            int[] colNums = getHeaderColumns(headers,wantedHeaders);
            String input = "";
            while((input = reader.readLine()) != null) {
                String[] cols = CSVReader.readLine(input,colNums);
                parse(cols);
            }
            stats[gp("student",tables)].println(studentId);
            stats[gp("student",tables)].println(DatabookLib.arrayJoin(ga("student"),","));
            stats[gp("student",tables)].println(studentId + ",2,10,2,2");
            
            stats[gp("major",tables)].println(majorId);
            stats[gp("major",tables)].println(DatabookLib.arrayJoin(ga("major"),","));
            stats[gp("major",tables)].println(majorId + "," + deptId + "," + majorId + "," + majorId);
            
            stats[gp("hasMajor",tables)].println(hasMajorId);
            stats[gp("hasMajor",tables)].println(DatabookLib.arrayJoin(ga("hasMajor"),","));
            stats[gp("hasMajor",tables)].println(studentId + "," + majorId + ",19,2");
            
            for (int i = 0; i < handles.length; i++) {
                handles[i].close();
                stats[i].close();
            }
        } else {
            throw new FileNotFoundException(src + " does not exists");
        }
    }
    
    private static String[] ga(String table) {
        return tableHeaders[gp(table,tables)];
    }
    
    private static void parse(String[] columns) {
        
        int sid = parseStudent(columns);
        parseMajors(columns,sid);        
    }
    
    private static int parseStudent(String[] line) {
        // Student Stuff
        int id = studentId++;
        String[] arr = ga("student");
        String[] students = new String[arr.length];
        students[gp("Student_ID",arr)] = id + "";
        students[gp("Gender",arr)] = line[gp("LSA_GENDER_LD",wantedHeaders)];
        students[gp("Ethnicity",arr)] = line[gp("LSA_RACE_LD",wantedHeaders)];
        boolean graduated = false;
        for (int i = 1; i <= 13; i++) {
            if (line[gp("DEG_" + i,wantedHeaders)].equals("Y")) {
                graduated = true;
                break;
            }
        }
        students[gp("Graduated",arr)] = graduated ? "Y" : "N";
        students[gp("Transfered",arr)] = line[gp("LSA_NEW_CONT_STATUS",wantedHeaders)].indexOf("Transfer") != -1 ? "Y" : "N";
        handles[gp("student",tables)].println(DatabookLib.arrayJoin(students,","));
        return id;
    }
    
    private static void parseMajors(String[] line,int student) {
        // Major Stuff
        String[] arr = ga("major");
        String[] harr = ga("hasMajor");
        for (int i = 1; i <= 13; i++) {
            String major = line[gp("MAJOR_" + i,wantedHeaders)];
            if (major.equals("")) continue;
            int mid; 
            int did = 0;
            if (majorMap.containsKey(major)) {
                mid = majorMap.get(major).intValue();
            } else {
                mid = majorId++;
                majorMap.put(major,new Integer(mid));
                String[] majors = new String[arr.length];
                majors[gp("Major_ID",arr)] = mid + "";
                majors[gp("Dept_ID",arr)] = did + "";
                majors[gp("Designator",arr)] = major;
                majors[gp("Full_name",arr)] = major;
                handles[gp("major",tables)].println(DatabookLib.arrayJoin(majors,","));
            }
            String[] hm = new String[harr.length];
            hm[gp("Year",harr)] = (getYear(line[gp("COHORT_TERM",wantedHeaders)]) + (int)Math.floor(i/2)) + "";
            hm[gp("Semester",harr)] = (i%2 == 0) ? "SP":"FA";
            hm[gp("Student_ID",harr)] = student + "";
            hm[gp("Major_ID",harr)] = mid + "";
            handles[gp("hasMajor",tables)].println(DatabookLib.arrayJoin(hm,","));
            hasMajorId++;
        }
    }
    
    private static int getYear(String term) {
        return Integer.parseInt(term.substring(0,4));
    }/**/
}
